import { app, BrowserWindow, ipcMain, dialog, shell } from 'electron'
import { fileURLToPath } from 'node:url'
import * as path from 'node:path'
import * as fs from 'fs/promises'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

// The built directory structure
//
// ├─┬─┬ dist
// │ │ └── index.html
// │ │
// │ ├─┬ dist-electron
// │ │ ├── main.js
// │ │ └── preload.mjs
// │
process.env.APP_ROOT = path.join(__dirname, '..')

// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x
export const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']
export const MAIN_DIST = path.join(process.env.APP_ROOT, 'dist-electron')
export const RENDERER_DIST = path.join(process.env.APP_ROOT, 'dist')

process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT, 'public') : RENDERER_DIST

let win: BrowserWindow | null

// 数据存储路径
const DATA_DIR = path.join(app.getPath('userData'), 'data')
const CARDS_DIR = path.join(DATA_DIR, 'cards')
// 默认垃圾站路径
const DEFAULT_TRASH_DIR = path.join(DATA_DIR, 'trash')
// Legacy path, only used for migration
const LEGACY_CARDS_FILE = path.join(DATA_DIR, 'cards.json')

// 配置文件路径
const CONFIG_FILE = path.join(DATA_DIR, 'config.json')

// 确保数据目录存在
async function ensureDataDir() {
  try {
    await fs.access(DATA_DIR)
  } catch {
    await fs.mkdir(DATA_DIR, { recursive: true })
  }

  try {
    await fs.access(CARDS_DIR)
  } catch {
    await fs.mkdir(CARDS_DIR, { recursive: true })
  }
}

// 确保垃圾站目录存在
async function ensureTrashDir(trashDir: string) {
  try {
    await fs.access(trashDir)
  } catch {
    await fs.mkdir(trashDir, { recursive: true })
  }
}

// 读取配置
async function readConfig() {
  try {
    const data = await fs.readFile(CONFIG_FILE, 'utf-8')
    return JSON.parse(data)
  } catch {
    // 如果配置文件不存在或读取失败，返回默认配置
    return getDefaultConfig()
  }
}

// 保存配置
async function saveConfig(config: any) {
  try {
    // 确保数据目录存在
    await ensureDataDir()
    await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8')
    return true
  } catch (error) {
    console.error('Failed to save config:', error)
    throw error
  }
}

// 获取默认配置
function getDefaultConfig() {
  return {
    // 通用设置
    general: {
      language: 'zh-CN',
      // 删除通用日期时间格式
      // 特定字段格式
      startTimeFormat: {
        dateFormat: 'YYYY-MM-DD',
        timeFormat: '24',
        showTime: true,
        showSeconds: true
      },
      createdTimeFormat: {
        dateFormat: 'YYYY-MM-DD',
        timeFormat: '24',
        showTime: true,
        showSeconds: true
      },
      updatedTimeFormat: {
        dateFormat: 'YYYY-MM-DD',
        timeFormat: '24',
        showTime: true,
        showSeconds: false
      },
      // 添加外部链接访问方式设置
      externalLinkOpenMode: 'browser', // 'browser'表示使用本地浏览器打开，'internal'表示在应用内打开
    },
    // 编辑器设置
    editor: {
      uploadUrl: '',
      token: '',
      defaultEditorMode: 'richText',
      autoSave: true,
      autoSaveInterval: 5,
    },
    // 外观设置
    appearance: {
      theme: 'system',
      fontSize: 'medium',
      fontFamily: 'system',
    },
    // 数据源设置
    dataSource: {
      type: 'local', // 'local' | 'remote'
      apiBaseUrl: 'http://localhost:8080/api',
      useMockData: true, // 是否使用Mock数据
      localSavePath: '', // 卡片本地保存路径，默认为空使用应用默认路径
    },
    // 垃圾站设置
    trash: {
      path: '', // 垃圾站路径，默认为空使用应用默认路径
    }
  }
}

// 获取垃圾站路径
async function getTrashDir(): Promise<string> {
  const config = await readConfig();
  let trashDir = DEFAULT_TRASH_DIR; // 默认路径
  
  // 如果配置了垃圾站路径且不为空，则使用配置的路径
  if (config.dataSource && config.dataSource.trashPath && config.dataSource.trashPath.trim() !== '') {
    trashDir = config.dataSource.trashPath;
  } 
  // 如果配置了自定义卡片保存路径，则在其下创建trash子目录
  else if (config.dataSource && config.dataSource.localSavePath && config.dataSource.localSavePath.trim() !== '') {
    trashDir = path.join(config.dataSource.localSavePath, 'trash');
  }
  
  // 确保垃圾站目录存在
  await ensureTrashDir(trashDir);
  
  return trashDir;
}

// 获取卡片保存路径
async function getCardsDir(): Promise<string> {
  const config = await readConfig();
  let cardsDir = CARDS_DIR; // 默认路径
  
  // 如果配置了自定义路径且不为空，则使用自定义路径
  if (config.dataSource && config.dataSource.localSavePath && config.dataSource.localSavePath.trim() !== '') {
    cardsDir = config.dataSource.localSavePath;
    
    // 确保自定义目录存在
    try {
      await fs.access(cardsDir);
    } catch {
      await fs.mkdir(cardsDir, { recursive: true });
    }
  }
  
  return cardsDir;
}

// 读取卡片数据
async function readCards() {
  try {
    const cardsDir = await getCardsDir();
    
    // 从cards目录读取所有卡片文件
    const files = await fs.readdir(cardsDir);
    const cardFiles = files.filter(file => file.endsWith('.json'));

    const cards = [];
    for (const file of cardFiles) {
      try {
        const cardData = await fs.readFile(path.join(cardsDir, file), 'utf-8');
        cards.push(JSON.parse(cardData));
      } catch (error) {
        console.error(`Failed to read card file: ${file}`, error);
      }
    }

    return { cards };
  } catch (error) {
    console.error('Failed to read cards directory:', error);

    // 如果新卡片目录读取失败，尝试从旧的单文件中读取
    try {
      const data = await fs.readFile(LEGACY_CARDS_FILE, 'utf-8')
      return JSON.parse(data)
    } catch {
      return { cards: [] }
    }
  }
}

// 读取垃圾站卡片数据
async function readTrashCards(page: number, pageSize: number) {
  try {
    const trashDir = await getTrashDir();
    
    // 从trash目录读取所有卡片文件
    const files = await fs.readdir(trashDir);
    const cardFiles = files.filter(file => file.endsWith('.json'));

    const allCards = [];
    for (const file of cardFiles) {
      try {
        const cardData = await fs.readFile(path.join(trashDir, file), 'utf-8');
        allCards.push(JSON.parse(cardData));
      } catch (error) {
        console.error(`Failed to read trash card file: ${file}`, error);
      }
    }
    
    // 按卡片更新时间降序排序
    allCards.sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime());
    
    // 分页处理
    const startIndex = (page - 1) * pageSize;
    const cards = allCards.slice(startIndex, startIndex + pageSize);
    
    return { 
      cards,
      hasMore: startIndex + pageSize < allCards.length,
      total: allCards.length
    };
  } catch (error) {
    console.error('Failed to read trash cards directory:', error);
    return { 
      cards: [],
      hasMore: false,
      total: 0
    };
  }
}

// 生成安全的文件名
function generateSafeFilename(title: string, timestamp: number): string {
  // 移除不安全的文件名字符
  const safeTitle = title.replace(/[\\/:*?"<>|]/g, '_');
  return `${safeTitle}_${timestamp}.json`;
}

// 保存单个卡片到文件
async function saveCardToFile(card: any): Promise<void> {
  try {
    const cardsDir = await getCardsDir();

    const timestamp = Date.now();
    const filename = generateSafeFilename(card.title, timestamp);
    const filePath = path.join(cardsDir, filename);

    await fs.writeFile(filePath, JSON.stringify(card, null, 2), 'utf-8');

    // 如果是更新现有卡片，删除旧文件
    // 注意：这里需要先查找是否有其他文件包含相同的卡片ID
    const files = await fs.readdir(cardsDir);
    for (const file of files) {
      if (file === filename) continue;

      try {
        const filePath = path.join(cardsDir, file);
        const content = await fs.readFile(filePath, 'utf-8');
        const existingCard = JSON.parse(content);

        if (existingCard.id === card.id) {
          await fs.unlink(filePath);
        }
      } catch (error) {
        console.error(`Failed to process file during card update: ${file}`, error);
      }
    }
  } catch (error) {
    console.error('Failed to save card to file:', error);
    throw error;
  }
}

// 将卡片移动到垃圾站
async function moveCardToTrash(cardId: string): Promise<boolean> {
  try {
    const cardsDir = await getCardsDir();
    const trashDir = await getTrashDir();
    let cardFound = false;
    
    const files = await fs.readdir(cardsDir);

    for (const file of files) {
      try {
        const filePath = path.join(cardsDir, file);
        const content = await fs.readFile(filePath, 'utf-8');
        const card = JSON.parse(content);

        if (card.id === cardId) {
          // 添加删除时间标记
          card.trashedAt = new Date().toISOString();
          
          // 保存到垃圾站
          const trashFilePath = path.join(trashDir, file);
          await fs.writeFile(trashFilePath, JSON.stringify(card, null, 2), 'utf-8');
          
          // 从原目录删除
          await fs.unlink(filePath);
          cardFound = true;
          break;
        }
      } catch (error) {
        console.error(`Failed to process file during moving card to trash: ${file}`, error);
      }
    }
    
    return cardFound;
  } catch (error) {
    console.error('Failed to move card to trash:', error);
    throw error;
  }
}

// 从垃圾站恢复卡片
async function restoreCardFromTrash(cardId: string): Promise<boolean> {
  try {
    const cardsDir = await getCardsDir();
    const trashDir = await getTrashDir();
    let cardFound = false;
    
    const files = await fs.readdir(trashDir);

    for (const file of files) {
      try {
        const filePath = path.join(trashDir, file);
        const content = await fs.readFile(filePath, 'utf-8');
        const card = JSON.parse(content);

        if (card.id === cardId) {
          // 删除垃圾站标记
          delete card.trashedAt;
          
          // 更新恢复时间
          card.updated = new Date().toISOString();
          
          // 保存到正常目录
          await saveCardToFile(card);
          
          // 从垃圾站删除
          await fs.unlink(filePath);
          cardFound = true;
          break;
        }
      } catch (error) {
        console.error(`Failed to process file during restoring card from trash: ${file}`, error);
      }
    }
    
    return cardFound;
  } catch (error) {
    console.error('Failed to restore card from trash:', error);
    throw error;
  }
}

// 永久删除垃圾站中的卡片
async function permanentlyDeleteCard(cardId: string): Promise<boolean> {
  try {
    const trashDir = await getTrashDir();
    let cardFound = false;
    
    const files = await fs.readdir(trashDir);

    for (const file of files) {
      try {
        const filePath = path.join(trashDir, file);
        const content = await fs.readFile(filePath, 'utf-8');
        const card = JSON.parse(content);

        if (card.id === cardId) {
          // 从垃圾站永久删除
          await fs.unlink(filePath);
          cardFound = true;
          break;
        }
      } catch (error) {
        console.error(`Failed to process file during permanent card deletion: ${file}`, error);
      }
    }
    
    return cardFound;
  } catch (error) {
    console.error('Failed to permanently delete card:', error);
    throw error;
  }
}

// 清空垃圾站
async function emptyTrash(): Promise<boolean> {
  try {
    const trashDir = await getTrashDir();
    const files = await fs.readdir(trashDir);
    const cardFiles = files.filter(file => file.endsWith('.json'));
    
    for (const file of cardFiles) {
      try {
        const filePath = path.join(trashDir, file);
        await fs.unlink(filePath);
      } catch (error) {
        console.error(`Failed to delete file during emptying trash: ${file}`, error);
      }
    }
    
    return true;
  } catch (error) {
    console.error('Failed to empty trash:', error);
    throw error;
  }
}

// 删除卡片文件（转为移动到垃圾站）
async function deleteCardFile(cardId: string): Promise<void> {
  // 直接调用移动到垃圾站的功能
  const success = await moveCardToTrash(cardId);
  
  if (!success) {
    throw new Error(`Card with id ${cardId} not found`);
  }
}

// 初始化数据存储
async function initializeStorage() {
  await ensureDataDir();
  await ensureTrashDir(await getTrashDir());

  // 检查旧的存储文件是否存在并迁移数据
  try {
    // 首先检查文件是否存在，避免显示ENOENT错误
    try {
      await fs.access(LEGACY_CARDS_FILE);
    } catch {
      // 文件不存在，直接返回，不需要记录错误
      return;
    }
    
    // 如果能到这里，说明文件确实存在
    const oldData = await fs.readFile(LEGACY_CARDS_FILE, 'utf-8');
    const { cards } = JSON.parse(oldData);

    if (Array.isArray(cards) && cards.length > 0) {
      // 迁移每张卡片到单独的文件
      for (const card of cards) {
        await saveCardToFile(card);
      }

      // 备份旧文件并删除
      const backupPath = `${LEGACY_CARDS_FILE}.backup.${Date.now()}`;
      await fs.rename(LEGACY_CARDS_FILE, backupPath);
      console.log('Successfully migrated legacy cards to new file system.');
    }
  } catch (error) {
    // 仅处理文件存在但内容解析或迁移出错的情况
    if (error instanceof Error) {
      console.log('Error during migration of existing legacy file:', error.message);
    } else {
      console.log('Unknown error during migration.');
    }
  }
}

// 为渲染进程提供格式化后的当前时间
async function getCurrentDateTime(fieldType: string = 'general'): Promise<string> {
  try {
    // 读取用户配置的时间格式
    const config = await readConfig();
    const now = new Date();
    
    // 根据不同字段类型选择不同的格式化配置
    let formatConfig;
    switch (fieldType) {
      case 'start':
        formatConfig = config.general.startTimeFormat || {};
        break;
      case 'created':
        formatConfig = config.general.createdTimeFormat || {};
        break;
      case 'updated':
        formatConfig = config.general.updatedTimeFormat || {};
        break;
      default:
        // 默认配置
        formatConfig = {
          dateFormat: 'YYYY-MM-DD',
          timeFormat: '24',
          showTime: true,
          showSeconds: true
        };
    }
    
    // 格式化日期部分
    let dateFormat = 'yyyy-MM-dd';
    switch (formatConfig.dateFormat) {
      case 'MM/DD/YYYY': dateFormat = 'MM/dd/yyyy'; break;
      case 'DD/MM/YYYY': dateFormat = 'dd/MM/yyyy'; break;
      case 'YYYY年MM月DD日': dateFormat = 'yyyy年MM月dd日'; break;
      case 'DD MMM YYYY': dateFormat = 'dd MMM yyyy'; break;
      case 'MMM DD, YYYY': dateFormat = 'MMM dd, yyyy'; break;
      default: dateFormat = 'yyyy-MM-dd'; // 默认 YYYY-MM-DD
    }
    
    // 格式化时间部分
    let timeFormat = formatConfig.timeFormat === '12' ? 'hh:mm' : 'HH:mm';
    if (formatConfig.showSeconds) {
      timeFormat += ':ss';
    }
    if (formatConfig.timeFormat === '12') {
      timeFormat += ' a'; // 添加上午/下午标识
    }
    
    // 组合日期和时间
    const format = formatConfig.showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
    
    // 使用 date-fns 格式化
    const { format: dateFnsFormat } = await import('date-fns');
    const { zhCN, enUS } = await import('date-fns/locale');
    
    // 根据配置使用合适的语言
    const locale = config.general.language === 'zh-CN' ? zhCN : enUS;
    
    // 返回格式化后的时间
    return dateFnsFormat(now, format, { locale });
  } catch (error) {
    console.error('Failed to format current date time:', error);
    // 出错时返回标准 ISO 格式的时间
    return new Date().toISOString();
  }
}

// 主进程初始化
async function initialize() {
  await initializeStorage()

  // IPC 通信处理
  ipcMain.handle('loadCards', async () => {
    try {
      return await readCards()
    } catch (error) {
      console.error('Failed to load cards:', error)
      throw error
    }
  })

  ipcMain.handle('saveCard', async (_, card) => {
    try {
      // 验证卡片数据
      if (!card || typeof card !== 'object') {
        throw new Error('Invalid card data')
      }

      // 确保所有必要的字段都已填写
      if (!card.id) {
        // ID should be generated by the client using snowflake algorithm
        // but just in case it's missing, we'll handle it here
        console.error('Card ID should be provided by the client')
        // We can't generate a snowflake ID here, but we'll use a UUID as fallback
        card.id = crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(36) + Math.random().toString(36).substr(2)
      }

      card.created = card.created || new Date().toISOString()
      card.updated = new Date().toISOString()

      // 保存卡片到单独的文件
      await saveCardToFile(card);

      // 返回更新后的卡片数据
      return card;
    } catch (error) {
      console.error('Failed to save card:', error)
      throw error
    }
  })

  ipcMain.handle('deleteCard', async (_, cardId) => {
    try {
      // 删除卡片文件（现在会移动到垃圾站）
      await deleteCardFile(cardId);
      return true;
    } catch (error) {
      console.error('Failed to delete card:', error)
      throw error
    }
  })

  // 垃圾站相关的IPC处理
  ipcMain.handle('getTrashCards', async (_, page, pageSize) => {
    try {
      return await readTrashCards(page, pageSize);
    } catch (error) {
      console.error('Failed to load trash cards:', error);
      throw error
    }
  })

  ipcMain.handle('moveCardToTrash', async (_, cardId) => {
    try {
      return await moveCardToTrash(cardId);
    } catch (error) {
      console.error('Failed to move card to trash:', error);
      throw error
    }
  })

  ipcMain.handle('restoreCardFromTrash', async (_, cardId) => {
    try {
      return await restoreCardFromTrash(cardId);
    } catch (error) {
      console.error('Failed to restore card from trash:', error);
      throw error
    }
  })

  ipcMain.handle('permanentlyDeleteCard', async (_, cardId) => {
    try {
      return await permanentlyDeleteCard(cardId);
    } catch (error) {
      console.error('Failed to permanently delete card:', error);
      throw error
    }
  })

  ipcMain.handle('emptyTrash', async () => {
    try {
      return await emptyTrash();
    } catch (error) {
      console.error('Failed to empty trash:', error);
      throw error
    }
  })

  // 配置相关的IPC处理
  ipcMain.handle('loadConfig', async () => {
    try {
      return await readConfig()
    } catch (error) {
      console.error('Failed to load config:', error)
      throw error
    }
  })

  ipcMain.handle('saveConfig', async (_, config) => {
    try {
      await saveConfig(config)
      return true
    } catch (error) {
      console.error('Failed to save config:', error)
      throw error
    }
  })
  
  // 获取默认卡片保存路径
  ipcMain.handle('getDefaultPath', async () => {
    try {
      return { defaultPath: CARDS_DIR }
    } catch (error) {
      console.error('Failed to get default path:', error)
      throw error
    }
  })
  
  // 获取默认垃圾站路径
  ipcMain.handle('getDefaultTrashPath', async () => {
    try {
      return { defaultTrashPath: DEFAULT_TRASH_DIR }
    } catch (error) {
      console.error('Failed to get default trash path:', error)
      throw error
    }
  })
  
  // 文件夹选择对话框
  ipcMain.handle('selectFolder', async () => {
    try {
      if (!win) return { canceled: true, filePaths: [] }
      
      const result = await dialog.showOpenDialog(win, {
        properties: ['openDirectory', 'createDirectory'],
        title: '选择目录'
      })
      
      return result
    } catch (error) {
      console.error('Failed to open folder dialog:', error);
      throw error
    }
  })

  // 添加一个IPC通道处理程序用于打开外部链接
  ipcMain.handle('open-external-url', async (_, url) => {
    try {
      await shell.openExternal(url);
      return { success: true };
    } catch (error: any) {
      console.error('Failed to open external URL:', error);
      return { success: false, error: error.message };
    }
  });

  // 添加一个IPC通道处理程序用于在应用内打开外部链接
  ipcMain.handle('open-internal-window', async (_, url) => {
    try {
      // 检查主窗口是否存在
      if (!win) {
        return { success: false, error: 'Main window not available' };
      }
      
      // 创建一个新的浏览器窗口
      const childWindow = new BrowserWindow({
        width: 1024,
        height: 768,
        parent: win, // 设置父窗口，使其与主窗口关联
        modal: false, // 非模态窗口
        webPreferences: {
          nodeIntegration: false,
          contextIsolation: true,
          sandbox: true,
          webSecurity: true, // 开启Web安全性
        },
        // 隐藏菜单栏
        autoHideMenuBar: true,
      });
      
      // 设置窗口标题
      childWindow.setTitle('外部链接 - ' + url);
      
      // 移除应用程序菜单
      childWindow.setMenu(null);
      
      // 设置Content Security Policy
      childWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => {
        callback({
          responseHeaders: {
            ...details.responseHeaders,
            'Content-Security-Policy': [
              "default-src 'self' * data: 'unsafe-inline'; script-src 'self' * 'unsafe-inline'; style-src 'self' * 'unsafe-inline'; img-src 'self' * data:; font-src 'self' * data:;"
            ]
          }
        });
      });
      
      // 加载URL
      await childWindow.loadURL(url);
      
      // 添加窗口关闭事件
      childWindow.on('closed', () => {
        // 从窗口管理中移除引用
        // TODO: 如果需要窗口管理，这里可以添加窗口管理代码
      });
      
      return { success: true };
    } catch (error: any) {
      console.error('Failed to open internal window:', error);
      return { success: false, error: error.message };
    }
  });

  // 添加一个IPC通道处理程序用于获取当前时间
  ipcMain.handle('getCurrentDateTime', async (_, fieldType) => {
    try {
      return await getCurrentDateTime(fieldType);
    } catch (error) {
      console.error('Failed to get current date time:', error);
      throw error;
    }
  });
}

function createWindow() {
  win = new BrowserWindow({
    show: false, // 先隐藏窗口，等加载完成后再显示
    width: 1000,
    icon: path.join(process.env.VITE_PUBLIC, 'electron-vite.svg'),
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'), // Changed from preload.mjs to preload.js
      // Enable security features
      nodeIntegration: false,
      contextIsolation: true,
      sandbox: true,
      webSecurity: true,
   
    },
    // 隐藏菜单栏
    autoHideMenuBar: true,
  })

  // 设置窗口默认全屏
  win.maximize();

  // 移除应用程序菜单
  win.setMenu(null);

  // Set Content Security Policy
  win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
    callback({
      responseHeaders: {
        ...details.responseHeaders,
        'Content-Security-Policy': [
          "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:;"
        ]
      }
    })
  })

  // 生产环境中不要自动打开DevTools
  if ((process.env.NODE_ENV as string) == 'development' || (process.env.NODE_ENV as string) == 'dev') {
    win.webContents.openDevTools();
  }


  // Test active push message to Renderer-process.
  win.webContents.on('did-finish-load', () => {
    win?.webContents.send('main-process-message', (new Date).toLocaleString())
  })

  if (VITE_DEV_SERVER_URL) {
    win.loadURL(VITE_DEV_SERVER_URL)
  } else {
    // win.loadFile('dist/index.html')
    win.loadFile(path.join(RENDERER_DIST, 'index.html'))
  }

  win.once('ready-to-show', () => {
    win?.show()
  } )
  win.on('closed', () => {  
    win = null
  })
}

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
    win = null
  }
})

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

app.whenReady().then(async () => {
  await initialize()
  createWindow()
})
